package priv.xakml;
import cn.hutool.Hutool;
import cn.hutool.core.util.ArrayUtil;
import com.sun.javafx.binding.StringFormatter;
import me.tongfei.progressbar.ProgressBar;
import me.tongfei.progressbar.ProgressBarBuilder;
import me.tongfei.progressbar.ProgressBarStyle;
import org.apache.commons.cli.*;
import priv.xakml.fileassistant.entity.DbHelper;
import priv.xakml.fileassistant.entity.Dir;
import priv.xakml.fileassistant.entity.SubDir;
import priv.xakml.fileassistant.entity.file;
import priv.xakml.toolkit.BinaryConverter;
//import priv.xakml.toolkit.BinaryConverter;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

// 参考资料
// https://www.lynnjy.cn/2018/08/01/mvn-pack/
//https://cloud.tencent.com/developer/article/1354070
//https://www.jianshu.com/p/e581fff1cf87
//https://blog.csdn.net/qq_32736999/article/details/93395246
//https:blog.csdn.net/qq_29318383/article/details/91442842

/**
 * commons-cli 参考资料
 * https://blog.csdn.net/yamaxifeng_132/article/details/87822812
 *
 */

public class Main {

    public static void main(String[] args) throws ParseException, SQLException, ClassNotFoundException {
        // write your code here
        CommandLineParser parser = new DefaultParser();
        Options options = new Options();
        //$ java -jar App.jar -h
        options.addOption("d", "directory", true, "目标目录");
//        options.addOption("d",  true, "目标目录");
        //$java -jar App.jar --file test.txt
        options.addOption("f", "file", true, "directory input");
        options.addOption("h", "help", false, "使用方法及参数说明");

        CommandLine commandLine = parser.parse(options, args);
        if(commandLine.hasOption('h')){
            HelpFormatter hf = new HelpFormatter();
            hf.printHelp("Options", options);
            return;
        }

        if (commandLine.hasOption("d")) {
            System.out.println("请稍后, 正在执行准备工作...");
            String dir = commandLine.getOptionValue("d");
            if(dir == null || dir.length() == 0)
            {
                System.out.println("argument d is null or empty");
                System.exit(0);
            }
            System.out.println(String.format("d=%s",dir));
            File file = new File(dir);
            if(!file.exists()) {
                System.out.println(String.format("指定的目录不存在%s",dir));
                System.exit(0);
            }
            if (!file.isDirectory()) {
                System.out.println("请输入有效的目录路径");
                System.exit(0);
            }

            DbHelper sqliteDbHelper = new DbHelper();
            Dir home_dir = new Dir();
            home_dir.setDirPath(file.getAbsolutePath());
            home_dir.setDirPathHash(cn.hutool.crypto.digest.DigestUtil.md5Hex(file.getAbsolutePath()).toUpperCase());
            if(!sqliteDbHelper.saveDir(home_dir))
            {
                sqliteDbHelper.dispose();
                System.out.println("保存主目录失败，程序已推出！");
                return;
            }

            SubDir[] subDirs = null;
            List<File> sub_dirs = Main.loopDirectories(file);
            if(null != sub_dirs && sub_dirs.size()> 0){
                subDirs=  new SubDir[sub_dirs.size()];
                int index = 0;
                sqliteDbHelper.beginTransaction();
                for (File sub_dir : sub_dirs){
                    subDirs[index] = new SubDir();
                    subDirs[index].setHomeDirId(home_dir.getId());
                    subDirs[index].setSubDir_Path(sub_dir.getAbsolutePath());
                    subDirs[index].setSubDir_Path_hash(cn.hutool.crypto.digest.DigestUtil.md5Hex(sub_dir.getAbsolutePath()).toUpperCase());
                    sqliteDbHelper.saveSubDir(subDirs[index]);
                    index ++;
                }
                sqliteDbHelper.CommitTransaction();
            }


            //检索根目录的文件列表
            File[] files = file.listFiles();
            for (File f : files) {
                //System.out.print(f.getName() + "=");
                if(f.isFile()) {
                    FileHashTool tool = new FileHashTool(f);
                    String hash_hex = tool.getMd5Value();
                    String hash_hex_sha1 = tool.getSHA1Value();
//                    System.out.println(String.format("MD5=%s,SHA1=%s",hash_hex,hash_hex_sha1));
                }
            }

            //检索所有子目录的文件列表
            if(null != subDirs && subDirs.length> 0) {
                sqliteDbHelper.beginTransaction();
                int subdir_index = 1;
                for (SubDir subdir : subDirs){
                    String subdir_process_percent = Main.getSubDirPercentString(subdir_index,subDirs.length);
                    System.out.println(String.format("正在索引%s--> %s",subdir_process_percent,subdir.getSubDir_Path()));
                    File[] subdir_files = cn.hutool.core.io.FileUtil.ls(subdir.getSubDir_Path());
                    int subdir_files_index = 1;
                   // System.out.println(String.format("(%d/%d)",subdir_index,subDirs.length));
//                    ProgressBar pb = new ProgressBarBuilder()
////                            .setTaskName(String.format("%s",subdir.getSubDir_Path()))
//                            .setTaskName(getProgressBarTaskName(subdir_index,subDirs.length))
//                            .setInitialMax(subdir_files.length)
//                            .setStyle(ProgressBarStyle.COLORFUL_UNICODE_BLOCK)
//                            .setUnit("f", 1)
//                            .build();
                    subdir_index ++;
                    int index = 1;
                    int percent_string_length = Main.getProProcessPercent(index,subdir_files.length).length();
                    System.out.print(String.format("%-"+percent_string_length+"s",' '));
                    for (File f : subdir_files){
                        Main.printBackspaceChar(percent_string_length);
                        System.out.print(String.format("%s", Main.getProProcessPercent(index,subdir_files.length)));
                        if(f.isDirectory()) {
                            index ++;
                            continue;
                        }
                        if(cn.hutool.core.io.FileUtil.isEmpty(f)) {
                            index++;
                            continue;
                        }

                        priv.xakml.fileassistant.entity.file file1 = new file();
                        file1.setFolder_id(subdir.getId());
                        file1.setFile_path(f.getAbsolutePath());
                        file1.setFile_name(f.getName());
                        file1.setFile_size(f.length());
                        file1.setMd5(cn.hutool.crypto.digest.DigestUtil.md5Hex(f).toUpperCase());
                        file1.setSha1(cn.hutool.crypto.digest.DigestUtil.sha1Hex(f).toUpperCase());
                        sqliteDbHelper.saveFile(file1);
//                        pb.step();
                        index++;
                    }
                }
                sqliteDbHelper.CommitTransaction();
            }

            System.exit(0);
        }

        System.out.println("hello world");
    }

    //region 扩展方法
//    public static String GetFileMd5Value(File file) {
//        InputStream stream = null;
//        try {
//            stream = Files.newInputStream(file.toPath(), StandardOpenOption.READ);
//            MessageDigest digest = MessageDigest.getInstance("MD5");
//            byte[] buf = new byte[8192];
//            int len;
//            while ((len = stream.read(buf)) > 0) {
//                digest.update(buf, 0, len);
//            }
//            byte[] hash = digest.digest();
//            String hash_hex = BinaryConverter.toHexString(hash, true);
//            return hash_hex;
//        } catch (IOException e) {
//            e.printStackTrace();
//            return "";
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//            return "";
//        }
//    }

    /**
     * 递归检索给定目录下的所有子目录
     * @param file 给定的目录
     * @return
     */
    public static List<File> loopDirectories(File file){
        final List<File> fileList = new ArrayList<>();
        if (null == file || false == file.exists() || file.isFile()) {
            return fileList;
        }

        if (file.isDirectory()) {
            fileList.add(file);
            final File[] subFiles = file.listFiles();
            if (ArrayUtil.isNotEmpty(subFiles)) {
                for (File tmp : subFiles) {
                    fileList.addAll(loopDirectories(tmp));
                }
            }
        }

        return fileList;
    }

    /**
     * 生成进度条任务名称（前后多次名称字符宽度必须相同,动态适配合适的字符宽度）
     * @param current_index
     * @param total
     * @return
     */
    private static String getProProcessPercent(int current_index,int total){
        String total_string = String.format("%s", total);
        int total_string_length = total_string.length();
        String format_string = "(%-" + total_string_length + "d/" + "%s)";
        return  String.format(format_string, current_index,total_string);
    }

    /**
     *  计算子目录进度提示文字, 和方法"getProgressBarTaskName"效果相同
     * @param current_subdir_index
     * @param total
     * @return
     */
    private static String getSubDirPercentString(int current_subdir_index,int total){
        String total_string = String.format("%s", total);
        int total_string_length = total_string.length();
        String format_string = "(%-" + total_string_length + "d/" + "%s)";
        return  String.format(format_string, current_subdir_index,total_string);
    }

    private static void printBackspaceChar(int print_count){
        for (int i=0;i<print_count;i++){
            System.out.print('\b');
        }
    }

    //endregion
}
